﻿/*
 *  Author: Louis A. Leskoviansky
 *  Company: Artemis Solutions Group (http://www.artemis-solutions.com)
 */


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.SessionState;
using System.Web.UI;

namespace AjaxControlFramework
{
    public class DiskStateStrategy : StateStrategy
    {
        //------// Properties \\--------------------------------------------\\
        private string _stateCachePath = null;
        public virtual string StateCachePath
        {
            get
            {
                if (_stateCachePath == null)
                {
                    _stateCachePath = base.Page.MapPath("~/App_Data/AJAX Control State/");
                }

                return _stateCachePath;
            }
        }
        //------\\ Properties //--------------------------------------------//



        //------// Constructors \\------------------------------------------\\
        public DiskStateStrategy(Control targetControl)
            : base(targetControl)
        { }
        //------\\ Constructors //------------------------------------------//



        //------// Methods \\-----------------------------------------------\\
        protected override void PersistStateToMedium(string state)
        {
            string stateFileName = GetStateFileName();

            if (!Directory.Exists(StateCachePath))
            {
                Directory.CreateDirectory(StateCachePath);
            }


            bool saveFileNameToCache = false;

            if (!File.Exists(StateCachePath + stateFileName))
            {
                saveFileNameToCache = true;
            }

            File.WriteAllText(StateCachePath + stateFileName, state);


            // Save the file name to the cache and provide and anonymous handler to delete the file once the 
            // cache value has expired.
            if (saveFileNameToCache)
            {
                HttpContext.Current.Cache.Add(stateFileName, (byte)1, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, HttpContext.Current.Session.Timeout, 0), CacheItemPriority.High, delegate(string key, object value, CacheItemRemovedReason reason)
                {
                    if (File.Exists(StateCachePath + key))
                    {
                        File.Delete(StateCachePath + key);
                    }
                });
            }
        }


        protected override Pair RestoreStateFromMedium()
        {
            string stateFileName = GetStateFileName();
            string stateFullPath = StateCachePath + stateFileName;

            string controlState = null;

            if (File.Exists(stateFullPath))
            {
                controlState = File.ReadAllText(StateCachePath + stateFileName);

                if (!String.IsNullOrEmpty(controlState))
                {
                    return (Pair)base.StateFormatter.Deserialize(controlState);
                }
            }

            return null;
        }


        protected virtual string GetStateFileName()
        {
            // TODO: THIS WILL CAUSE "PATH TOO LONG" EXCEPTIONS AND OFTEN SESSION ID IS NULL!!! AHHHHHHH!!!!!!
            return new SessionIDManager().GetSessionID(HttpContext.Current) + "_" + TargetControl.UniqueID /*+ "_" + HttpUtility.UrlEncode(TargetControl.Page.Request.Url.PathAndQuery)*/ + ".state";
        }
        //------\\ Methods //-----------------------------------------------//
    }
}
